﻿using SuperSocket.ClientEngine;
using SuperSocket.ProtoBase;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Web.Script.Serialization;
using System.Windows.Forms;

namespace ETS_FinancialData_sync_toolsForClient
{
    public partial class workerStation : Form
    {
        private string ServerIP; //IP
        private int port;   //端口
        private bool _Error = false;
        private IPEndPoint port1;
        public bool IsConnected
        {
            get { return client.IsConnected; }
        }
        public delegate void DeClosed(object sender, EventArgs e);
        public event DeClosed Closed;

        public workerStation()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
            client = new EasyClient();
            client.Connected += client_Connected;
            client.Error += _TcpClient_Error;
            //获取链接配置
            getsqlconn();
            if (!connected())
            {
                apendText("数据库未连接，请检查您的sql服务并重启客户端！\n");
                MessageBox.Show("数据库未连接，请检查您的sql服务！\n并重启客户端。");

            }
            try
            {
                if (File.Exists(strFilePath))//读取时先要判读INI文件是否存在
                {
                    strSec = "ADMIN";
                    ServerIP = ContentValue(strSec, "ip");
                    port = Convert.ToInt32(ContentValue(strSec, "port"));
                    this.Text = "账务同步工具客户端 版本：" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();// +"  服务器ip" + ServerIP.Remove(ServerIP.LastIndexOf('.') + 1) + "***:" + port;
                    txtHost.Text = ServerIP;
                    txtPort.Text = ContentValue(strSec, "port");
                }
                else
                {
                    MessageBox.Show("lxerp.ini文件不存在！");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("请检查lxerp.ini文件ADMIN组下是否有ip、port等值！\n\r" + ex.Message, "获取配置文件参数失败");
            }


            // Initialize the client with the receive filter and request handler
            client.Initialize(new MyTerminatorReceiveFilter(), (request) =>
            {
                // handle the received request
                apendText(request.Key + "##" + request.Body);
                if (request.Key.Trim() == "Heart")
                {
                    // MessageBox.Show(request.Body);
                }
                else if (request.Key.Trim() == "return")
                {
                    List<Dictionary<string, object>> getJsData = null;
                    var js = new JavaScriptSerializer();
                    var info = js.Deserialize<List<Dictionary<string, object>>>(request.Body);
                    getJsData = info as List<Dictionary<string, object>>;
                    //MessageBox.Show(request.Body);
                    if (getJsData[0]["status"].ToString() == "1")
                    {
                        if (exec_sql("update t_SyncFinancialRecords set fstatus=0 where sync_id='" + getJsData[0]["sync_id"] + "'") == 0)
                        {
                            saveErrLog("sql修改失败：" + "update t_SyncFinancialRecords set fstatus=0 where sync_id='" + getJsData[0]["sync_id"] + "'  返回0条记录", DateTime.Now.ToString("yyyy-MM-dd") + "-sql_err");
                        }
                    }
                    else
                    {
                        //服务器处理失败了

                    }
                }
            });
            port1 = new System.Net.IPEndPoint(IPAddress.Parse(txtHost.Text.Trim()), Convert.ToInt32(txtPort.Text.Trim()));
            //心跳计时器定义
            _HeartBeat = new System.Timers.Timer(1000);
            _HeartBeat.Elapsed += TimerElapsed;
            _HeartBeat.AutoReset = true;
        }

        public bool connected()
        {
            SqlConnection conn = new SqlConnection(Sqlconn);
            try
            {

                conn.Open();
            }
            catch (Exception ex)
            {
                richTextBox1.AppendText(ex.Message);
                return false;
            }
            if (conn.State == ConnectionState.Open)
            {
                return true;
            }
            return false;
        }

        #region //根据传入的sql语句返回受影响的行数
        /// <summary>
        /// 根据传入的sql语句返回受影响的行数
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public int exec_sql(string sql)
        {
            int result = 0;
            SqlConnection conn = new SqlConnection(Sqlconn);
            try
            {
                SqlCommand cmd = new SqlCommand(sql, conn);
                conn.Open();
                SqlCommand cmd2 = new SqlCommand("set Context_Info 0x123456789", conn);

                result = cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                saveErrLog(sql + ex.Message, DateTime.Now.ToString("yyyy-MM-dd") + "-sql_err");
                return result;
            }

            finally
            {
                conn.Close();
            }

            return result;
        }
        #endregion

        #region "声明变量"

        /// <summary>
        /// 写入INI文件
        /// </summary>
        /// <param name="section">节点名称[如[TypeName]]</param>
        /// <param name="key">键</param>
        /// <param name="val">值</param>
        /// <param name="filepath">文件路径</param>
        /// <returns></returns>
        [System.Runtime.InteropServices.DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filepath);
        /// <summary>
        /// 读取INI文件
        /// </summary>
        /// <param name="section">节点名称</param>
        /// <param name="key">键</param>
        /// <param name="def">值</param>
        /// <param name="retval">stringbulider对象</param>
        /// <param name="size">字节大小</param>
        /// <param name="filePath">文件路径</param>
        /// <returns></returns>
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retval, int size, string filePath);

        private string strFilePath = Application.StartupPath + "\\lxerp.ini";//获取INI文件路径
        private string strSec = ""; //INI文件名

        #endregion

        #region "自定义读取INI文件中的内容方法"
        /// <summary>
        /// 自定义读取INI文件中的内容方法
        /// </summary>
        /// <param name="Section">键</param>
        /// <param name="key">值</param>
        /// <returns></returns>
        private string ContentValue(string Section, string key)
        {

            StringBuilder temp = new StringBuilder(1024);
            GetPrivateProfileString(Section, key, "", temp, 1024, strFilePath);
            return temp.ToString();
        }
        #endregion

        #region "获取sqlconn连接参数"

        private string sqlconn;

        public string Sqlconn
        {
            get { return sqlconn; }
            set { sqlconn = value; }
        }

        public void getsqlconn()
        {
            try
            {
                if (File.Exists(strFilePath))//读取时先要判读INI文件是否存在
                {

                    //strSec = Path.GetFileNameWithoutExtension(strFilePath);
                    strSec = "Connection";
                    string Database = ContentValue(strSec, "Database");
                    dbName = Database;
                    string ServerName = ContentValue(strSec, "ServerName");
                    string LogId = ContentValue(strSec, "LogId");
                    string Logpass = ContentValue(strSec, "Logpass");
                    sqlconn = @"server=" + ServerName + ";database = " + Database + "; uid =" + LogId + "; pwd = " + Logpass + ";";
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        #endregion

        public void do_result(string jsonTextFromServer)
        {
            //if(jsonTextFromServer.Length<2)
            //MessageBox.Show("[]".Length.ToString());
            MessageBox.Show(jsonTextFromServer + "\n\r长度：" + jsonTextFromServer.Length);
        }
        public string dbName = null;
        EasyClient client;
        private void workerStation_Load(object sender, EventArgs e)
        {
            ifHasDelayField();
            //自动上线
            btnConnect_Click(sender, e);
        }

        private bool TryConnect()
        {

            _Error = true;
            _HeartBeat.Stop();

            for (int i = 0; i < 3; i++)
            {
                client.Close();
                client.ConnectAsync(port1).Wait();
                Thread.Sleep(1000);
                if (this.IsConnected)
                {
                    _HeartBeat.Start();
                    _Error = false;
                    return true;
                }
            }
            _Error = false;
            return false;
        }
        void client_Connected(object sender, EventArgs e)
        {
            _HeartBeat.Start();
        }

        void _TcpClient_Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e)
        {
            _HeartBeat.Stop();
            _Error = true;
            if (!_Error)
            {
                if (!this.TryConnect())
                    Closed(client, e);
            }
        }
        private System.Timers.Timer _HeartBeat;
        private void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e)//心跳
        {

            if (IsConnected)
            {
                byte[] sendData = Encoding.UTF8.GetBytes(string.Format("Heart#{0}\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
                client.Send(new ArraySegment<byte>(sendData));
            }
        }

        #region 给richTextbox追加文本
        public void apendText(string text)
        {

            Action<string> actionDelegate = (x) =>
            {
                if (this.richTextBox1.Text.Length > 20000)
                {
                    this.richTextBox1.Text = this.richTextBox1.Text.Substring(20000, this.richTextBox1.Text.Length - 20000);
                }
                this.richTextBox1.AppendText("\n\r" + text);
                this.richTextBox1.ScrollToCaret();
            };
            this.richTextBox1.Invoke(actionDelegate, "\n\r" + text);

        }
        #endregion

        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (!IsConnected)
            {
                btnConnect.Enabled = false;
                //上线则开始连接socket服务
                client.ConnectAsync(port1).Wait();

                //发送消息到服务端
                if (IsConnected)
                    client.Send(new ArraySegment<byte>(Encoding.UTF8.GetBytes("Heart#hello i am a client!\r\n")));



                //启动定时器执行后台任务
                timer1.Start();
            }

            //Thread worker = new Thread(delegate()
            //  {
            //      if (!IsConnected)
            //      {
            //          btnConnect.Enabled = false;
            //          //上线则开始连接socket服务
            //          client.ConnectAsync(port1).Wait();

            //          //发送消息到服务端
            //          if (IsConnected)
            //              client.Send(new ArraySegment<byte>(Encoding.UTF8.GetBytes("Heart#hello i am a client!\r\n")));



            //          //启动定时器执行后台任务
            //          timer1.Start();
            //      }
            //  });
            //worker.IsBackground = true;
            //worker.Start();
        }


        private DateTime LastSendTimes;
        //数据库是否存在延迟发送的两个字段
        private static bool hasDelayField;

        public static bool HasDelayField
        {
            get { return hasDelayField; }
            set { hasDelayField = value; }
        }
        //BG_JSON发送次数
        private static int sendCounts;

        public static int SendCounts
        {
            get { return sendCounts; }
            set { sendCounts = value; }
        }
        /// <summary>
        /// 判断t_SyncFinancialRecords表是否存在
        /// SendCounts和LastSendTimes字段
        /// </summary>
        public void ifHasDelayField()
        {
            string sql = "select COUNT(*) from syscolumns where id=object_id('t_SyncFinancialRecords') and (name ='SendCounts' or name='LastSendTimes')";
            if (ifSync_idExist(sql) == 2)
            {
                HasDelayField = true; //开启延迟发送json的功能
            }
            else
            {
                HasDelayField = false;//屏蔽延迟发送json的功能，不影响老版本使用
                //是否自动增加这两个字段？
            }
        }
        #region //判断错误的sync_id是否在sync表存在
        /// <summary>
        /// 判断错误的sync_id是否在sync表存在
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public int ifSync_idExist(string sql)
        {
            int result = 0;
            SqlConnection conn = new SqlConnection(Sqlconn);
            try
            {

                SqlCommand cmd = new SqlCommand(sql, conn);
                conn.Open();
                result = int.Parse(cmd.ExecuteScalar().ToString());

            }
            catch (Exception ex)
            {
                saveErrLog(sql + ex.Message, DateTime.Now.ToString("yyyy-MM-dd") + "-sql_err");
                return result;
            }

            finally
            {
                conn.Close();

            }

            return result;
        }
        #endregion
        //获取并显示体育馆名称
        private void showClubName()
        {
            string sql_getClubList = "select namec,Localld from sys_company where Localld is not null";
            List<string> ClubList = new List<string>();
            SqlConnection cn = new SqlConnection(Sqlconn);
            SqlCommand cmd = new SqlCommand(sql_getClubList, cn);
            try
            {
                cn.Open();
                SqlDataReader dr = cmd.ExecuteReader();
                while (dr.Read())
                {
                    if (dr.GetValue(0).ToString().Length > 0)
                    {
                        ClubList.Add(dr.GetValue(0).ToString());

                    }
                }
                if (ClubList.Count > 0)
                {
                    if (ClubList.Count == 1)
                    {
                        notifyIcon1.Text += ("\n场馆:【" + ClubList[0] + "】");
                    }
                    else
                    {
                        notifyIcon1.Text += ("\n场馆:【" + ClubList[0] + "】");
                    }

                }
            }
            catch (Exception ex)
            {
                saveErrLog(ex.Message + " 场馆名称:获取失败！\n\r" + ex.StackTrace, DateTime.Now.ToString("yyyy-MM-dd") + "-sql_err");
            }
            finally
            {
                cn.Close();
            }
        }
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            SqlConnection cn = new SqlConnection(Sqlconn);
            try
            {
                getsqlconn();
                if (cn != null)
                {
                    cn.Open();
                }
                SqlCommand cmd = cn.CreateCommand();
                cmd.CommandText = "select * from t_SyncFinancialRecords  with(nolock) where fstatus=1 order by fdate";
                //cmd.CommandText = "select * from t_SyncFinancialRecords  with(nolock) where sync_id='67e68c47-fcf9-4fca-ac16-f60846c123b0' order by fdate";
                SqlDataReader dr = cmd.ExecuteReader();

                //定义一个字典，存储多少次，发送json的间隔时间,单位/s
                Dictionary<int, int> DictInterval = new Dictionary<int, int>();
                DictInterval[1] = 10;
                DictInterval[2] = 30;
                DictInterval[3] = 2 * 60;
                DictInterval[4] = 10 * 60;
                DictInterval[5] = 1 * 60 * 60;
                DictInterval[6] = 3 * 60 * 60;
                DictInterval[7] = 12 * 60 * 60;
                DictInterval[8] = 48 * 60 * 60;
                //client.Send(new ArraySegment<byte>(Encoding.Default.GetBytes("Json#无延期无转让无退卡赠送杯子一个  2016.7.12续费一年赠送舞蹈服一套参加砸金蛋活动立减200元" + "\r\n")));
                while (dr.Read())
                {
                    //延迟发送开关
                    //得确保程序启动前已经添加了这些SendCounts、LastSendTimes字段
                    if (HasDelayField)
                    {
                        //获取当前行的fstatus=1的fjson发了几次(SendCounts)，和上次发的时间(LastSendTimes)
                        if (dr["SendCounts"] == DBNull.Value)
                        {
                            SendCounts = 0;
                        }
                        else
                        {
                            SendCounts = Convert.ToInt32(dr["SendCounts"]);
                            if (dr["LastSendTimes"] != DBNull.Value)
                            {
                                LastSendTimes = Convert.ToDateTime(dr["LastSendTimes"]);
                            }
                        }
                        //如果符合字典里的次数和时间要求||次数SendCounts和时间LastSendTimes为null
                        switch (SendCounts)
                        {
                            //BGworkSendAndShowJSON()每次执行都会更新发送次数和发送时间
                            case 0: BGworkSendAndShowJSON(dr); break;
                            case 1: if (LastSendTimes.AddSeconds(DictInterval[1]) <= DateTime.Now) { BGworkSendAndShowJSON(dr); }; break;
                            case 2: if (LastSendTimes.AddSeconds(DictInterval[2]) <= DateTime.Now) { BGworkSendAndShowJSON(dr); }; break;
                            case 3: if (LastSendTimes.AddSeconds(DictInterval[3]) <= DateTime.Now) { BGworkSendAndShowJSON(dr); }; break;
                            case 4: if (LastSendTimes.AddSeconds(DictInterval[4]) <= DateTime.Now) { BGworkSendAndShowJSON(dr); }; break;
                            case 5: if (LastSendTimes.AddSeconds(DictInterval[5]) <= DateTime.Now) { BGworkSendAndShowJSON(dr); }; break;
                            case 6: if (LastSendTimes.AddSeconds(DictInterval[6]) <= DateTime.Now) { BGworkSendAndShowJSON(dr); }; break;
                            case 7: if (LastSendTimes.AddSeconds(DictInterval[7]) <= DateTime.Now) { BGworkSendAndShowJSON(dr); }; break;
                            case 8: if (LastSendTimes.AddSeconds(DictInterval[8]) <= DateTime.Now) { BGworkSendAndShowJSON(dr); }; break;
                            //-1：延迟发送成功返回0，-2意味着超过8次发送，每次都是失败，不再发送！
                            default: exec_sql("update t_SyncFinancialRecords set fstatus=-2 where sync_id='" + dr["sync_id"] + "'"); break;
                        }
                        //client.Send(new ArraySegment<byte>(Encoding.Default.GetBytes("Json#" + dr["fjson"].ToString() + "\r\n")));
                    }
                }
            }
            catch (Exception ex)
            {
                apendText(ex.Message);
                saveErrLog(ex.Message, "ex");
            }
            finally
            {
                if (cn != null)
                    cn.Close();
            }

        }

        private void BGworkSendAndShowJSON(SqlDataReader dr)
        {
            client.Send(new ArraySegment<byte>(Encoding.Default.GetBytes("Json#" + dr["fjson"].ToString().Replace("\r", " ").Replace("\n", " ") + "\r\n")));
            //已经发送过json给服务器，更新当前的发送次数和最后发送的时间
            if (HasDelayField)
            {
                if (exec_sql("update t_SyncFinancialRecords set SendCounts=" + (SendCounts + 1) + " , LastSendTimes='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "' where sync_id='" + dr["sync_id"] + "'") == 0)
                {
                    saveErrLog("sql修改失败：" + "update t_SyncFinancialRecords set SendCounts=" + (SendCounts + 1) + " , LastSendTimes='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "' where sync_id='" + dr["sync_id"] + "'" + "  返回0条记录", DateTime.Now.ToString("yyyy-MM-dd") + "-sql_delaySendJson");
                }
                else
                {
                    saveErrLog("sql修改成功：" + "update t_SyncFinancialRecords set SendCounts=" + (SendCounts + 1) + " , LastSendTimes='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "' where sync_id='" + dr["sync_id"] + "'", DateTime.Now.ToString("yyyy-MM-dd") + "-sql_delaySendJson");
                }
            }
        }
        #region //保存log
        public void saveErrLog(string log, string txtName)
        {
            //txtName = "log";
            log = DateTime.Now.ToString() + " : " + log;
            string path = Application.StartupPath + "\\";
            if (File.Exists(path + @"\" + txtName + ".txt"))
            {
                StreamWriter SW;
                SW = File.AppendText(path + @"\" + txtName + ".txt");
                SW.WriteLine(log + "\r\n");
                SW.Close();
            }
            else
            {
                StreamWriter SW;
                SW = File.CreateText(path + @"\" + txtName + ".txt");
                SW.WriteLine(log + "\r\n");
                SW.Close();
            }

        }
        #endregion

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            btnConnect.Enabled = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                if (IsConnected)
                {
                    if (!backgroundWorker1.IsBusy)
                        backgroundWorker1.RunWorkerAsync();
                }
                else
                {
                    TryConnect();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }


}

